package cn.geminis.workflow.service.controller;

import cn.geminis.workflow.service.service.engine.ExtensionElementUtils;
import cn.geminis.workflow.service.service.engine.expression.ExpressionValueContext;
import cn.geminis.workflow.service.service.engine.expression.GeminiExpressionManager;
import cn.geminis.workflow.service.utils.SpringUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.flowable.engine.ProcessEngine;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.xml.stream.XMLInputFactory;
import java.util.Map;

@RestController
@RequestMapping("/data")
@RequiredArgsConstructor
public class DataController {

    private static XMLInputFactory XML_FACTORY = XMLInputFactory.newInstance();

    static {
        XML_FACTORY.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
    }

    private final ProcessEngine engine;
    private final GeminiExpressionManager geminiExpressionManager;

    @GetMapping("/{taskInstanceId}")
    @SneakyThrows
    public Map<String, Object> taskData(@PathVariable String taskInstanceId) {
        var taskInstance = this.engine
                .getHistoryService()
                .createHistoricTaskInstanceQuery()
                .taskId(taskInstanceId)
                .singleResult();

        var valueContext = SpringUtils.getBean(ExpressionValueContext.class);
        valueContext.clear();
        valueContext.withProcess(taskInstance.getProcessInstanceId());
        valueContext.withTask(taskInstance);

        var bpmnModel = this.engine
                .getRepositoryService()
                .getBpmnModel(taskInstance.getProcessDefinitionId());
        var processModel = bpmnModel.getMainProcess();
        ExtensionElementUtils.get(processModel.getExtensionElements(), "dataUrl")
                .ifPresent((url) -> {
                    var urlFinal = (String) geminiExpressionManager.createExpression(url).getValue(null);
                    valueContext.withData(urlFinal);
                });
        var taskModel = processModel.getFlowElement(taskInstance.getTaskDefinitionKey());
        ExtensionElementUtils.get(taskModel.getExtensionElements(), "dataUrl")
                .ifPresent((url) -> {
                    var urlFinal = (String) geminiExpressionManager.createExpression(url).getValue(null);
                    valueContext.withData(urlFinal);
                });

        return valueContext.getVariables();
    }

}
